Element UI 二次封装实现下拉树组件 |
您所在的位置:网站首页 › 自定义组件 v-model › Element UI 二次封装实现下拉树组件 |
使用element ui 二次封装实现下拉树组件,可以搜索,可以动态绑定 一 实现效果图 1.1 单选模式 单选模式.gif 1.2 多选模式 多选模式.gif 二 相关说明 2.1 框架以及版本 1、element-ui 2.15.1 2 2、vue 2.6.11 2.2 组件概述封装的下拉树,结合了element ui中的下拉组件 el-select 与 树结构组件 el-tree,取两个组件中的一些属性,在此基础上进行的封装。其中可通过v-model对数据进行动态绑定。自行封装扩展性不高,可能会有一些问题,需求不同,可自行进行封装。 2.3 组件api 相关属性 属性 说明 类型 默认值 defaultValue/v-model 值 String, Number, Array - treeData 树结构数据源 Array [] treeProps 替换treeNode 中 label, children 字段为 treeData 中对应的字段 Object {label: ‘name’, children: ‘children’} nodeKey 树结构数据key取值,数据唯一,默认id String id clearable 是否显示清空功能 Boolean false multiple 是否多选 Boolean false placeholder 选择框默认文字 String 请选择 showSearch 是否显示搜索框 Boolean false searchPlaceholder 搜索框默认文字 String 请输入关键字 collapseTags 多选时是否将选中值按文字的形式展示 Boolean true2 相关方法 名称 说明 参数 change 数据发生变化 数据,选中的节点 removeTag 多选模式下,点击删除单个tag触发 当前选中的值 clear 清空选项触发 - 三 代码实现 3.1 组件页面代码 3.2 组件JS部分代码 const defaultProps = { children: 'children', // 子级字段 label: 'name' // 展示字段 } export default { name: 'CustomTreeSelect', model: { prop: "defaultValue", event: "change" }, props: { // v-model值 defaultValue: { type: [String, Number, Array] }, // 数据源 treeData: { type: Array, default () { return [] } }, // 替换 treeNode 中 label, children 字段为 treeData 中对应的字段 treeProps: { type: Object, default () { return defaultProps } }, // 树结构key的取值,数据唯一, 默认为id nodeKey: { type: String, default: 'id' }, // 是否显示清空功能 clearable: { type: Boolean, default: false }, // 是否多选 multiple: { type: Boolean, default: false }, // 选择框默认文字 placeholder: { type: String, default: '请选择' }, // 搜索框默认文字 searchPlaceholder: { type: String, default: '请输入关键字' }, // 是否显示搜索框 showSearch: { type: Boolean, default: false }, // 多选时是否将选中值按文字的形式展示 collapseTags: { type: Boolean, default: true } }, data() { return { // 下拉框选中值 selectValue: '', // 下拉框选中回显值 selectLabel: '', // 下拉框Option的值,设置为undefined,防止选中 selectOptionValue: undefined, // 树数据搜索内容 treeFilterText: '', // 默认展开 defaultExpandedKeys: [] } }, computed: { // 树结构是否显示复选框(多选情况下出现) showCheckbox () { return this.multiple }, // select 下拉框自定义的类名-可自行修改 popperClass () { let classNames = ['custom-tree-select-popper'] if (this.showSearch) { classNames.push('custom-tree-select-search') } return classNames.join(' ') }, // 下拉框实例 treeSelectRef () { return this.$refs.treeSelectRef }, // 树结构实例 optionTreeRef () { return this.$refs.optionTreeRef } }, watch: { // 监听默认值,对数据赋值 defaultValue: { deep: true, immediate: true, handler (newValue, oldValue) { const { multiple } = this if (newValue) { if (!this.reloadTreeCheck) this.handleSetTreeCheck(newValue); } else { this.selectValue = multiple ? [] : '' this.selectLabel = multiple ? [] : '' } } }, treeFilterText (value) { setTimeout(() => { this.handleInputChange(value) }, 300) } }, mounted () { // 重新加载树结构选中 false-加载 true-不加载 this.reloadTreeCheck = false }, methods: { /** 多选模式下,点击移除单个tag */ handleSelectRemoveTag (tag) { this.reloadTreeCheck = false const { selectValue } = this if (isArray(selectValue)) { this.selectValue.shift() } this.$emit('removeTag', tag) }, /** select框的清除按钮 */ handleSelectClear () { this.reloadTreeCheck = false const { multiple } = this const value = multiple ? [] : '' this.treeFilterText = '' this.selectValue = [ ...value ] this.selectLabel = [ ...value ] this.$emit('change', value, null) this.$emit('clear') }, /** 树节点 点击时 */ handleNodeClick (node) { const { treeProps, multiple, nodeKey } = this if (multiple) return if (node.children && node.children.length > 0) return this.selectValue = node[nodeKey] this.selectLabel = node[treeProps.label] this.$emit('change', this.selectValue, node) // 下拉框失去焦点,隐藏下拉面板 this.treeSelectRef.blur() // this.treeFilterText = '' }, /** 树节点 复选框选中时 */ handleTreeCheck (node, values) { const { treeProps } = this const { checkedKeys, checkedNodes } = values this.selectValue = checkedKeys const lableValues = checkedNodes.map(nodeItem => { return nodeItem[treeProps.label] }) this.selectLabel = lableValues this.$emit('change', checkedKeys, checkedNodes) }, /** 设置回显数据 */ handleSetTreeNode (value) { const { optionTreeRef, treeProps } = this this.selectValue = value if (isArray(value)) { // 多选 this.selectLabel = value.map(item => { const treeNode = optionTreeRef.getNode(item) return treeNode.data[treeProps.label] }) } else { // 单选 const treeNode = optionTreeRef.getNode(value) this.selectLabel = treeNode.data[treeProps.label] } }, /** 处理数据树结构展开,并处理选中效果 */ handleTreeExpandKeys (value) { const { optionTreeRef, multiple } = this if (isArray(value) && multiple) { optionTreeRef.setCheckedKeys(value) value.forEach(item => { const treeNode = optionTreeRef.getNode(item) if (treeNode && treeNode.parent) { this.setTreeExpandKeys(treeNode.parent) } }) } else { optionTreeRef.setCurrentKey(value) const treeNode = optionTreeRef.getNode(value) if (treeNode && treeNode.parent) { this.setTreeExpandKeys(treeNode.parent) } } }, /** 处理树结构父级展开 */ setTreeExpandKeys (node) { node.expanded = true if (node.parent) { this.setTreeExpandKeys(node.parent) } }, /** 搜索树节点 */ filterTreeNode (value, data, node) { if (!value) { // if (node.expanded) node.expanded = false return true } const { treeProps: { label } } = this return data[label].indexOf(value) !== -1; }, /** 设置树结构回显选中 */ handleSetTreeCheck (value) { if (!this.reloadTreeCheck && value) { this.$nextTick(() => { this.handleSetTreeNode(value) this.handleTreeExpandKeys(value) this.reloadTreeCheck = true }) } }, /** 搜索框中按下回车失去焦点触发 */ handleInputChange (value) { this.optionTreeRef.filter(value) } } } /** * 判断数据类型是否为数组 */ function isArray(arg) { if (typeof Array.isArray === 'undefined') { return Object.prototype.toString.call(arg) === '[object Array]' } return Array.isArray(arg) } 3.3 组件样式代码这里有覆盖修改到element-ui的原始样式, 注:如果需要修改下拉框的高度,修改样式代码中.el-select-dropdown__wrap 中的高度属性 .custom-tree-select-search { .el-select-dropdown__list { padding: 0; } } .custom-tree-select-popper { .el-scrollbar { .el-select-dropdown__wrap { max-height: 365px !important; } .el-scrollbar__bar.is-vertical { z-index: 3; } } } .tree-select-search { position: sticky; top: 0; z-index: 2; display: block; padding: 6px; background: #fff; } .tree-select-option-item { background: #fff; overflow: scroll; height: 200px; overflow-x: hidden; } .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{ height: auto; min-height: 200px; padding: 0; overflow: hidden; } 四 如何使用 4.1 组件引入注册后页面 4.2 参数设置 export default { data () { return { treeData: [ { id: "321C8FF6CC6046D79CD8877526054BCF", text: "1100 北京市本级", name: "1100 北京市本级", code: "1100" }, { id: "157EAB9EA1A34D0F824E97C2C7D9F0CA", text: "1101 市辖区", name: "1101 市辖区", code: "1101", children: [ { id: "B08F7DB39F124ACFB2171508D8C5C0FD", text: "110101 东城区", name: "110101 东城区", code: "110101" }, { id: "2AF3A9766AAD433A95D4EADE5FB97839", text: "110102 西城区", name: "110102 西城区", code: "110102" }, { id: "A2058EAE12674B3D9BA3710C87DDB111", text: "110105 朝阳区", name: "110105 朝阳区", code: "110105" }, { id: "C6BC2FE9FE86493291EE59171133ABB5", text: "110106 丰台区", name: "110106 丰台区", code: "110106" }, { id: "06E478CB634F4FC19EC0381D55751218", text: "110107 石景山区", name: "110107 石景山区", code: "110107" }, { id: "DD0B1A29473D4053989938700B73AE26", text: "110108 海淀区", name: "110108 海淀区", code: "110108" }, { id: "5D3FF6E7729E43F9B813EAAB80796E41", text: "110109 门头沟区", name: "110109 门头沟区", code: "110109" }, { id: "349609893FAC47BC97509B8FC411059A", text: "110111 房山区", name: "110111 房山区", code: "110111" }, { id: "1E5B2DC4A1E84C959BB78D6E1B49A1DF", text: "110112 通州区", name: "110112 通州区", code: "110112" }, { id: "2C9DC40AEFF8454ABF8A2EE6AD0A2DB5", text: "110113 顺义区", name: "110113 顺义区", code: "110113" }, { id: "5C0342E4E41841AD837E365DB79E81B7", text: "110114 昌平区", name: "110114 昌平区", code: "110114" }, { id: "DF25016580634FD39307FC0E18E7CF4F", text: "110115 大兴区", name: "110115 大兴区", code: "110115" }, { id: "8DC99ABF109D40ED899552A08FE07C63", text: "110116 怀柔区", name: "110116 怀柔区", code: "110116" }, { id: "9D2DA21BD26C40CC90B8BB26E1B437AC", text: "110117 平谷区", name: "110117 平谷区", code: "110117" }, { id: "AD5172DDD7D547F5A06F022D64EB4DF5", text: "110118 密云区", name: "110118 密云区", code: "110118" }, { id: "78B4DA4936A44314AD801B15988707D4", text: "110119 延庆区", name: "110119 延庆区", code: "110119" } ] }, { id: "E8ADAB8AFDB24F77B3FA89ED7E9A9F15", text: "1102 县", name: "1102 县", code: "1102" } ], treeProps: { label: 'name', children: 'children' }, treeValue: [], } } } 参考文章https://element.eleme.cn/#/zh-CN https://blog.csdn.net/R_xxxxx/article/details/106112583 https://blog.csdn.net/sleepwalker_1992/article/details/87894588 https://www.jianshu.com/p/47e13795cfe7 https://blog.csdn.net/Mrchai521/article/details/114993368 https://blog.csdn.net/qq_41791303/article/details/103710456 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |